#include <fstream>
#include <vector>
#include <string>
#include <sstream>

#include "headers/FileLoader.h"


static const char dizzy_header[] = 
    { 
        'N','E','S', 0x1A,
        0x10,0x00,0x71,0x40,0x00,0x00, 
        0x00,0x00,0x00,0x00,0x00,0x00 
    };
      

int FileLoader::Init() {
    
    Bank.resize(0x10);
    for (int i=0; i<0x10; i++) {
        Bank[i].resize(0x4000);
    }
    
}
    
    
int FileLoader::LoadFile(const char* filename) {
    
    std::ifstream file(filename, std::ifstream::binary);
    
    if (!file.is_open())
        return 1;
        
    Filename = filename;
        
    file.ignore(16);    
    
    for (int i=0; i<0x10; i++)
        for (int j=0; j<0x4000; j++)
            Bank[i][j] = file.get();
    
    file.close();
        
    return 0;
    
}


void FileLoader::SetBank(int bank_id){
    
    BankCurrent = bank_id;

}


int FileLoader::CurrentBank() {
    
    return BankCurrent;
    
}


unsigned char FileLoader::Read(unsigned int address) const {
    
    if (address>=0x8000 && address<0xC000)
        return Bank[BankCurrent].at(address - 0x8000);
    else
        if (address>=0xC000 && address<0x10000)
            return Bank[0x0F].at(address-0xC000);
    
    return 0;

}

void FileLoader::Write(unsigned int address, unsigned char data)  {
    
    if (address>=0x8000 && address<0xC000)
        Bank[BankCurrent][address - 0x8000] = data;
    else
        if (address>=0xC000 && address<0x10000)
            Bank[0x0F][address-0xC000] = data;
}

int FileLoader::SaveToFile(const char* filename) const {
    
    std::ofstream file(filename, std::ifstream::binary);
    
    for (int i=0; i<0x10; i++)
        file << dizzy_header[i];
        
    for (int i=0; i<0x10; i++)
        for (int j=0; j<0x4000; j++)
            file << Bank[i][j];

            
    file.close();
    
    return 0;
}

int FileLoader::SaveBanks() const {
    
    std::ofstream file;
    std::ostringstream stream;
           
    for (int i=0; i<0x10; i++) {
        stream << "banks/Bank0" << std::hex << i;
        file.open(stream.str().c_str(), std::ios_base::binary);
        for (int j=0; j<0x4000; j++)
            file << Bank[i][j];
            
        file.close();
        stream.str("");
    }
    
    return 0;
}

int FileLoader::Uncompress(char* buffer, int address, int lenght) const {
    
    /* Dekompresja patternow (wszystkie patterny sa skompresowane tym algorytmem,
       mozliwe, ze pare innych rzeczy tez) */
    
    int RepeatID; //index bajtu ktory ma byc powtorzony
    int RepeatHowMany; //ilosc powtorzen
    int x; //ile bajtow odczytac
    
    int i = 0;
    
    while (lenght) {
        RepeatID = (Read(address)>>4)&0x0F;
        RepeatID++;
        RepeatHowMany = Read(address)&0x0F;
        int x = 0x10; //odczytaj 0x10 bajtow
        
        while (x>0) {
            address++;
            buffer[i] = Read(address); i++;
            RepeatID--;
            
            if (RepeatID==0)
                while(RepeatHowMany) {
                    x--;
                    if (x==0) break;
                    buffer[i] = Read(address); i++;
                    RepeatHowMany--;
                }
            x--;
        }
        address++;
        lenght--;
    }
    
}
        
            


        

    
    
    
    
